package org.e_gold.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.e_gold.dao.ContractDAO;
import org.e_gold.dao.EventDAO;
import org.e_gold.dto.Cookies;
import org.e_gold.model.Contract;
import org.e_gold.model.Event;
import org.e_gold.service.ContractService;
import org.e_gold.util.Bet365;
import org.e_gold.util.CalcUtil;
import org.e_gold.util.Enums;
import org.e_gold.util.StringUtil;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ContractServiceImpl extends _NavigatorService implements ContractService, Bet365 {

	private static final Logger logger = Logger.getLogger(ContractServiceImpl.class);
	@Autowired
	private EventDAO eventDAO;

	@Autowired
	private ContractDAO contractDAO;

	@Override
	public List<Contract> exposeAllContract(List<Event> events, Map<String, String> headers, Cookies cookies) {
		List<Contract> allContracts = new ArrayList<Contract>();
		//		Set<Contract> setContracts = new HashSet<Contract>();

		if (CollectionUtils.isNotEmpty(events)) {
			logger.info(":::::::::::::::::::::::::::");
			logger.info(":::::::::::::::::::::::::::");
			logger.info("::::::Start Contract:::::::");
			logger.info(":::::::::::::::::::::::::::");
			logger.info(":::::::::::::::::::::::::::");
			for (Event event : events) {
				//				eventContracts = exposeContract(event, headers, cookies);
				//				allContracts.addAll(eventContracts);

				logger.info("----------------------");
				logger.info("Begin expose contract - Event : " + event.getName());
				logger.info("----------------------");
				try {
					Document contractPage = redirectNavigator(event.getLocation());
					if (hasAllMarkets(contractPage)) {
						// get all markets link and update event DB
						Element eAllMarketsLink = contractPage.select(ALL_MARKETS_CLASS + " a").get(0);
						event.setLocation("../coupon/" + eAllMarketsLink.attr("href"));
						event.setLocationFull(BASE_SPORT + "coupon/" + eAllMarketsLink.attr(HREF));
						eventDAO.update(event);
						contractPage = redirectNavigator(event.getLocation());
					}
					Elements eSection = contractPage.select(SECTION);
					if(eSection != null && eSection.size() > 0){
						for(Element section : eSection){
							String sectionName = getElementSectionName(section);
							if(StringUtils.isEmpty(sectionName)){
								continue;
							}
							Elements eContract = section.select(ADD_TO_BET_SLIP_ANCHOR);


							for (Element e : eContract) {
								try {
									// insert new or populate old contract
									String contractStr = e.text();
									String contractType = StringUtil.getContractType(contractStr);
									Contract c = contractDAO.findByEventIdAndContractType(event.getId(), contractType);
									if (c == null) {
										c = new Contract();
										contractDAO.insert(c);
									}
									c.setSection(sectionName);
									c.setEvent(event);
									c.setRate(CalcUtil.getRate(contractStr));
									c.setContractType(contractType);
									c.setBetSlipUrl(e.attr("href"));
									//													setContracts.add(c);
									contractDAO.update(c);
									logger.info("Contract : " 
											+ event.getName() 
											+ " - " 
											+ event.getPlayTime() + "m" 
											+ "[" + event.getTotalGoal() + "]" 
											+ "[" + c.getSection() + "] - "
											+ c.getContractType() + " - " + c.getRate());
									allContracts.add(c);
								} catch (Exception e2) {
									logger.info("expose contract error : " + e.text());
								}
							}
						}
					}

					//									if (CollectionUtils.isNotEmpty(setContracts)) {
					//										event.setContracts(setContracts);
					//									}
				} catch (Exception e) {
					logger.info("Expose event error : " + event.getName());
				}
				logger.info("----------------------");
				logger.info("End expose contract - Event : " + event.getName());
				logger.info("----------------------");
			}
			logger.info(":::::::::::::::::::::::::::");
			logger.info(":::::::::::::::::::::::::::");
			logger.info("::::::End Contract:::::::");
			logger.info(":: Total exposed contracts : " + allContracts.size() + "  ::");
			logger.info(":::::::::::::::::::::::::::");
		}
		return allContracts;
	}

	@Override
	@Deprecated
	public Set<Contract> exposeContract(Event event, Map<String, String> headers, Cookies cookies) {
		logger.info("----------------------");
		logger.info("Begin expose contract - Event : " + event.getName());
		logger.info("----------------------");

		Set<Contract> setContracts = new HashSet<Contract>();

		try {
			Document contractPage = redirectNavigator(event.getLocation());
			if (hasAllMarkets(contractPage)) {
				// get all markets link and update event DB
				Element eAllMarketsLink = contractPage.select(ALL_MARKETS_CLASS + " a").get(0);
				event.setLocation("../coupon/" + eAllMarketsLink.attr("href"));
				event.setLocationFull(BASE_SPORT + "coupon/" + eAllMarketsLink.attr(HREF));
				eventDAO.update(event);
				contractPage = redirectNavigator(event.getLocation());
			}
			Elements eSection = contractPage.select(SECTION);
			if(eSection != null && eSection.size() > 0){
				for(Element section : eSection){
					String sectionName = getElementSectionName(section);

					Elements eContract = section.select(ADD_TO_BET_SLIP_ANCHOR);

					for (Element e : eContract) {
						try {
							// insert new or populate old contract
							String contractStr = e.text();
							String contractType = StringUtil.getContractType(contractStr);
							Contract c = contractDAO.findByEventIdAndContractTypeAndSection(event.getId(), contractType, sectionName);
							if (c == null) {
								c = new Contract();
								contractDAO.insert(c);
							}
							c.setSection(sectionName);
							c.setEvent(event);
							c.setRate(CalcUtil.getRate(contractStr));
							c.setContractType(contractType);
							c.setBetSlipUrl(e.attr("href"));
							setContracts.add(c);
							contractDAO.update(c);
							logger.info("Contract : " 
									+ event.getName() 
									+ " - " 
									+ event.getPlayTime() + "m" 
									+ "[" + event.getTotalGoal() + "]" 
									+ "[" + c.getSection() + "] - "
									+ c.getContractType() + " - " + c.getRate());
							//							lstContracts.add(c);
						} catch (Exception e2) {
							logger.info("expose contract error : " + e.text());
						}
					}
				}
			}
		} catch (Exception e) {
			logger.info("Expose event error : " + event.getName());
		}
		logger.info("----------------------");
		logger.info("End expose contract - Event : " + event.getName());
		logger.info("----------------------");

		return setContracts;
	}

	private String getElementSectionName(Element section) {
		String sectionName = StringUtils.EMPTY;
		try{

			Elements ele = section.select(CLASS_HEADER);
			if(ele != null && ele.size() > 0){
				sectionName = ele.get(0).text();
			}
			sectionName = Enums.ContractTypeEnum.fromDisplay(sectionName);
		} catch (Exception e) {
			logger.error(e);
		}
		return sectionName;
	}

	private boolean hasAllMarkets(Document contractPage) {

		try {
			return contractPage.select(ALL_MARKETS_CLASS).size() > 0;
		} catch (Exception e) {
			logger.error(e);
		}
		return false;
	}

	@Override
	public Contract getRunningContract() {

		return contractDAO.getRunningContract();
	}

	@Override
	public void updateFalseQualify() {

		contractDAO.updateFalseQualify();
	}

	@Override
	public void updateFalseQualifyContract(List<Contract> lstContract) {
		StringBuilder sb = new StringBuilder();
		for(Contract ct : lstContract){
			sb.append(",");
			sb.append(ct.getId());
		}
		String idList = sb.substring(1).toLowerCase();
		contractDAO.updateFalseQualifyContract(idList);
	}

}
